//
// Created by konglinglong on 2020/9/8.
//

#include <stdio.h>
#include <iostream>
#include "../lib/doctest.h"
#include "../../include/utils/varRingBuffer.h"

TEST_SUITE ("VAR_RB_TS")
{
    TEST_CASE ("VAR_RB_TC")
    {
        int32_t rc;
        uint32_t loop;
        S_VarRingBuffer* pRingBuffer;
        uint32_t ringBuffType[] = { VAR_RB_TYPE_NONE, VAR_RB_TYPE_SPSC, VAR_RB_TYPE_MPSC };
        SUBCASE("VAR_RB_SC_BASE")
        {
            for (loop = 0; loop < ARRAY_SIZE(ringBuffType); loop++)
            {
                pRingBuffer = VarRB_Create(NULL, 1024 * 1024, ringBuffType[loop]);
                REQUIRE(pRingBuffer);
                VarRB_Destroy(pRingBuffer);
            }
        }

        SUBCASE("VAR_RB_SC_DUMP")
        {
            char dumpBuffer[2048];

            for (loop = 0; loop < ARRAY_SIZE(ringBuffType); loop++)
            {
                pRingBuffer = VarRB_Create(NULL, 1024 * 1024, ringBuffType[loop]);
                REQUIRE(pRingBuffer);

                VarRB_Dump(pRingBuffer, dumpBuffer, sizeof(dumpBuffer));
                printf("%s\n", dumpBuffer);

                VarRB_Destroy(pRingBuffer);
            }
        }

        SUBCASE("VAR_RB_SC_READ_WRITE")
        {
            char* pBuffer;
            uint32_t buffSize;
            for (loop = 0; loop < ARRAY_SIZE(ringBuffType); loop++)
            {
                pRingBuffer = VarRB_Create(NULL, 1024 * 1024, ringBuffType[loop]);
                REQUIRE(pRingBuffer);

                pBuffer = (char*)VarRB_WriteRequest(pRingBuffer, 1024);
                REQUIRE(pBuffer);
                rc = VarRB_WriteCommit(pRingBuffer, pBuffer);
                REQUIRE(CSP_RC_OK == rc);

                pBuffer = (char*)VarRB_ReadRequest(pRingBuffer, &buffSize);
                REQUIRE(pBuffer);
                REQUIRE(1024 == buffSize);
                rc = VarRB_ReadConsume(pRingBuffer, pBuffer);
                REQUIRE(CSP_RC_OK == rc);

                VarRB_Destroy(pRingBuffer);
            }
        }

        SUBCASE("VAR_RB_SC_READ_WRITE2")
        {
            uint32_t loop;
            uint32_t loopCnt;
            char* pBuffer;
            uint32_t buffSize;

            for (loop = 0; loop < ARRAY_SIZE(ringBuffType); loop++)
            {
                pRingBuffer = VarRB_Create(NULL, 1024 * 1024, ringBuffType[loop]);
                REQUIRE(pRingBuffer);

                loopCnt = rand() % 10000;

                for (loop = 0; loop < loopCnt; loop++)
                {
                    pBuffer = (char*)VarRB_WriteRequest(pRingBuffer, 1024);
                    REQUIRE(pBuffer);
                    rc = VarRB_WriteCommit(pRingBuffer, pBuffer);
                    REQUIRE(CSP_RC_OK == rc);

                    pBuffer = (char*)VarRB_ReadRequest(pRingBuffer, &buffSize);
                    REQUIRE(pBuffer);
                    REQUIRE(1024 == buffSize);
                    rc = VarRB_ReadConsume(pRingBuffer, pBuffer);
                    REQUIRE(CSP_RC_OK == rc);
                }

                VarRB_Destroy(pRingBuffer);
            }
        }

        SUBCASE("VAR_RB_SC_READ_WRITE3")
        {
            uint32_t loop;
            uint32_t loopCnt;
            char* pBuffer;
            uint32_t buffSize;

            for (loop = 0; loop < ARRAY_SIZE(ringBuffType); loop++)
            {
                pRingBuffer = VarRB_Create(NULL, 1024 * 1024, ringBuffType[loop]);
                REQUIRE(pRingBuffer);

                loopCnt = 0;

                while (1)
                {
                    pBuffer = (char*)VarRB_WriteRequest(pRingBuffer, (rand() % 1024) + 1);
                    if (pBuffer)
                    {
                        loopCnt++;
                        rc = VarRB_WriteCommit(pRingBuffer, pBuffer);
                        REQUIRE(CSP_RC_OK == rc);
                    }
                    else
                    {
                        break;
                    }
                }
                REQUIRE(loopCnt == VarRB_Count(pRingBuffer));

                for (loop = 0; loop < loopCnt; loop++)
                {
                    pBuffer = (char*)VarRB_ReadRequest(pRingBuffer, &buffSize);
                    REQUIRE(pBuffer);
                    rc = VarRB_ReadConsume(pRingBuffer, pBuffer);
                    REQUIRE(CSP_RC_OK == rc);
                }
                REQUIRE(0 == VarRB_Count(pRingBuffer));

                VarRB_Destroy(pRingBuffer);
            }
        }

        SUBCASE("VAR_RB_SC_PUT_GET")
        {
            uint32_t loop;
            uint32_t loopCnt;
            uint32_t buffer[1024 / sizeof(uint32_t)];
            uint32_t buffSize;

            for (loop = 0; loop < ARRAY_SIZE(ringBuffType); loop++)
            {
                pRingBuffer = VarRB_Create(NULL, 1024 * 1024, ringBuffType[loop]);
                REQUIRE(pRingBuffer);

                loopCnt = 0;

                while (1)
                {
                    buffer[0] = loopCnt;
                    rc = VarRB_Put(pRingBuffer, buffer, (rand() % (sizeof(buffer) - 4)) + 4);
                    if (CSP_RC_OK == rc)
                    {
                        loopCnt++;
                    }
                    else
                    {
                        break;
                    }
                }
                REQUIRE(loopCnt == VarRB_Count(pRingBuffer));

                for (loop = 0; loop < loopCnt; loop++)
                {
                    buffSize = sizeof(buffer);
                    rc = VarRB_Get(pRingBuffer, buffer, &buffSize);
                    REQUIRE(CSP_RC_OK == rc);
                    REQUIRE(loop == buffer[0]);
                }
                REQUIRE(0 == VarRB_Count(pRingBuffer));

                VarRB_Destroy(pRingBuffer);
            }
        }

        SUBCASE("VAR_RB_SC_PUT_GET_SHM")
        {
            uint32_t loop;
            uint32_t loopCnt;
            uint32_t buffer[1024 / sizeof(uint32_t)];
            uint32_t buffSize;

            for (loop = 0; loop < ARRAY_SIZE(ringBuffType); loop++)
            {
                pRingBuffer = VarRB_Create("uint_test_vrb_shm", 1024 * 1024, ringBuffType[loop]);
                REQUIRE(pRingBuffer);

                loopCnt = 0;

                while (1)
                {
                    buffer[0] = loopCnt;
                    rc = VarRB_Put(pRingBuffer, buffer, (rand() % (sizeof(buffer) - 4)) + 4);
                    if (CSP_RC_OK == rc)
                    {
                        loopCnt++;
                    }
                    else
                    {
                        break;
                    }
                }
                REQUIRE(loopCnt == VarRB_Count(pRingBuffer));

                for (loop = 0; loop < loopCnt; loop++)
                {
                    buffSize = sizeof(buffer);
                    rc = VarRB_Get(pRingBuffer, buffer, &buffSize);
                    REQUIRE(CSP_RC_OK == rc);
                    REQUIRE(loop == buffer[0]);
                }
                REQUIRE(0 == VarRB_Count(pRingBuffer));

                VarRB_Destroy(pRingBuffer);
            }
        }

        REQUIRE(OS_MemGetAllocCount() == OS_MemGetFreeCount());
    }
}
